package com.nononsenseapps.feeder.ui.feed

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
import android.view.View
import android.view.ViewTreeObserver
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.nononsenseapps.feeder.ui.R
import com.nononsenseapps.feeder.db.view.PreviewItem
import com.nononsenseapps.feeder.ui.common.SwipeDismissTouchListener
import android.text.Spannable
import android.text.SpannableString
import android.text.style.TextAppearanceSpan
import android.view.ContextMenu
import android.view.MenuInflater
import android.widget.ImageView
import com.gitee.wsl.android.ext.device.clipboardString
import com.nononsenseapps.feeder.db.ARG
import com.nononsenseapps.feeder.db.SYSTEM_FEED_LIST
import com.nononsenseapps.feeder.db.entity.PreLoadStateHelper
import com.nononsenseapps.feeder.db.room.*
import com.nononsenseapps.feeder.glide.GlideImageLoader
import com.nononsenseapps.feeder.ui.EditFavoriteActivity
import com.nononsenseapps.feeder.util.*


abstract class AbstractFeedItemHolder(val view: View, protected val actionCallback: ActionCallback,val viewModel:Boolean) : RecyclerView.ViewHolder(view), View.OnClickListener, ViewTreeObserver.OnPreDrawListener,View.OnCreateContextMenuListener {
    protected val titleTextView: TextView = view.findViewById(R.id.story_snippet)
    val dateTextView: TextView = view.findViewById(R.id.story_date)
    val authorTextView: TextView = view.findViewById(R.id.story_author)
    protected val bgFrame: View = view.findViewById(R.id.swiping_item)
    protected val checkLeft: View = view.findViewById(R.id.check_left)
    protected val checkRight: View = view.findViewById(R.id.check_right)
    protected val checkBg: View = view.findViewById(R.id.check_bg)

    protected  val feedThumbImageView:ImageView=view.findViewById(R.id.feed_thumb)

    var rssItem: PreviewItem? = null

    val tags :TextView = view.findViewById(R.id.story_tags)

    init {
        feedThumbImageView.visibility=View.INVISIBLE
        initView()
        initListener()
        if(!viewModel)
           initContextMenu()
    }

    open fun initView(){}

    open fun initListener(){
        view.setOnClickListener(this)
        if(!viewModel)
            view.setOnTouchListener( SwipeDismissTouchListener(view, null, object :  SwipeDismissTouchListener.DismissCallbacks {
            override fun canDismiss(token: Any?): Boolean = rssItem != null

            override fun onDismiss(view: View, token: Any?, goingRight:Boolean) {
                if(goingRight)
                    openItemInWebView(context = view.context)
                else
                    actionCallback.onDismiss(rssItem)
            }

            /**
             * Called when a swipe is started.
             *
             * @param goingRight true if swiping to the right, false if left
             */
            override fun onSwipeStarted(goingRight: Boolean) {
                actionCallback.onSwipeStarted()

                view.context?.let { context ->
                    val bgColor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        context.getColor(R.color.window_background)
                    } else {
                        @Suppress("DEPRECATION")
                        context.resources.getColor(R.color.window_background)
                    }
                    bgFrame.setBackgroundColor(bgColor)
                }

                checkBg.visibility = View.VISIBLE
                if (goingRight) {
                    checkLeft.visibility = View.VISIBLE
                } else {
                    checkRight.visibility = View.VISIBLE
                }
            }

            /**
             * Called when user doesn't swipe all the way.
             */
            override fun onSwipeCancelled() {
                actionCallback.onSwipeCancelled()

                checkBg.visibility = View.INVISIBLE
                checkLeft.visibility = View.INVISIBLE
                checkRight.visibility = View.INVISIBLE

                bgFrame.background = null
            }

            /**
             * @return the subview which should move
             */
            override fun getSwipingView(): View {
                return bgFrame
            }
        }))

        authorTextView.setOnClickListener(View.OnClickListener {
            actionCallback.onAuthorItemClick(rssItem!!)
        })
    }

    open fun initContextMenu(){
        view.setOnCreateContextMenuListener(this)
    }

    open fun resetView(){
        checkBg.visibility = View.INVISIBLE
        checkLeft.visibility = View.INVISIBLE
        checkRight.visibility = View.INVISIBLE
        bgFrame.clearAnimation()
        bgFrame.alpha = 1.0f
        bgFrame.translationX = 0.0f
        bgFrame.background = null
        feedThumbImageView.visibility=View.INVISIBLE
    }

    open fun fillTitle(forceRead: Boolean = false) {
        titleTextView.visibility = View.VISIBLE
        rssItem?.let { rssItem ->
            // \u2014 is a EM-dash, basically a long version of '-'
            val temps = rssItem.plainTitle
            val textSpan = SpannableString(temps)
            textSpan.setSpan(TextAppearanceSpan(view.context, R.style.TextAppearance_ListItem_Body),
                    rssItem.plainTitle.length, temps.length,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

            if (rssItem.unread && !forceRead) {
                textSpan.setSpan(TextAppearanceSpan(view.context, R.style.TextAppearance_ListItem_Title),
                        0, rssItem.plainTitle.length,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            } else {
                textSpan.setSpan(TextAppearanceSpan(view.context, R.style.TextAppearance_ListItem_Title_Read),
                        0, rssItem.plainTitle.length,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            titleTextView.text = textSpan
        }
    }

    /**
     * OnItemClickListener replacement.
     *
     *
     * If a feeditem does not have any content,
     * then it opens the link in the browser directly.
     *
     * @param view
     */
    override fun onClick(view: View) {
        val context = view.context
        if (context != null) {
            val defaultOpenItemWith = PrefUtils.shouldOpenItemWith(context)
            val openItemWith = when (defaultOpenItemWith) {
                PREF_VAL_OPEN_WITH_READER -> {
                    if (rssItem?.wordCount!! > 0) {
                        defaultOpenItemWith
                    } else {
                        PrefUtils.shouldOpenLinkWith(context)
                    }
                }
                else -> defaultOpenItemWith
            }

            actionCallback.onItemClick(rssItem!!)

            openItemToView(openItemWith,context)
        }
    }

    protected fun openItemInWebView(context: Context){
        actionCallback.onItemClick(rssItem!!)
        openItemToView(PREF_VAL_OPEN_WITH_WEBVIEW,context)
    }

    protected fun openItemToView(openItemWith: String, context: Context){
        if(viewModel) return
        when (openItemWith) {
            PREF_VAL_OPEN_WITH_BROWSER, PREF_VAL_OPEN_WITH_WEBVIEW -> {
                // Mark as read
                rssItem?.let {
                    actionCallback.markAsReadHistory(it)
                }

                when (openItemWith) {
                    PREF_VAL_OPEN_WITH_BROWSER -> {
                        // Open in browser since no content was posted
                        rssItem?.link?.let { link ->
                            openLinkInBrowser(context, link)
                        }
                    }
                    else -> {
                        rssItem?.let {
                            actionCallback.navToReaderWebViewFragment(it.link,it.enclosureLink)
                        }
                    }
                }
            }
            else -> {
                rssItem?.let {
                    actionCallback.navToReaderFragment()
                }
            }
        }
    }

    override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
         v?.context?.let {context->
             if (menu != null) {
                 MenuInflater(context).inflate(R.menu.contextmenu_feedfragment, menu)

                 val linkStr=naiveFindUrlLink(titleTextView.text.toString())


                 menu.findItem(R.id.action_mark_feature).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markItemFeature(it)
                     }
                     true
                 }

                 menu.findItem(R.id.action_remove_feature).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.removeItemFeature(it)
                     }
                     true
                 }

                 menu.findItem(R.id.action_mark_as_read_late).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.moveItemToFeed(it, READ_LATE_FEED_ID)
                     }
                     true
                 }


                 menu.findItem(R.id.action_mark_as_memo).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.moveItemToFeed(it, MEMO_FEED_ID)
                     }
                     true
                 }

                 menu.findItem(R.id.action_show_current_feature).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.showCurrentFeature(it)
                     }
                     true
                 }

                 menu.findItem(R.id.action_mark_as_favorite).setOnMenuItemClickListener {
                     rssItem?.let {
                         actionCallback.markAsFavorite(it)
                     }
                     true
                 }

                 menu.findItem(R.id.action_mark_as_store).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.moveItemToFeed(it, STORE_FEED_ID)
                     }
                     true
                 }

                 menu.findItem(R.id.action_delete).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.onItemDelete(it)
                     }
                     true
                 }
                 menu.findItem(R.id. action_mark_above_all_read).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markAboveAllRead(it)
                     }
                     true
                 }

                 menu.findItem(R.id.action_share).setOnMenuItemClickListener {
                     rssItem?.link?.let { link ->
                         val sendIntent: Intent = Intent().apply {
                             action = Intent.ACTION_SEND
                             type = "text/plain"
                             putExtra(Intent.EXTRA_TEXT, link)
                         }
                         val shareIntent = Intent.createChooser(sendIntent, null)
                         context.startActivity(shareIntent, null)
                     }
                     true
                 }

                 menu.findItem(R.id.action_speak).setOnMenuItemClickListener {
                     rssItem?.let {
                         actionCallback.speakFromCurrent(it)
                     }
                     true
                 }

                 menu.findItem(R.id.action_ad_feed_rule_text).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markAddFeedRule(it, adBlock = true, adImage = false, custom = false)
                     }
                     true
                 }

                 menu.findItem(R.id.action_ad_feed_rule_image).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markAddFeedRule(it, adBlock = true, adImage = true, custom = false)
                     }
                     true
                 }

                 menu.findItem(R.id.action_add_feed_rule).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markAddFeedRule(it, adBlock = false, adImage = false, custom = true)
                     }
                     true
                 }


                 menu.findItem(R.id.action_generate_QR_code).setOnMenuItemClickListener {
                     rssItem?.link?.let { link ->
                         actionCallback.generateQRCode(rssItem!!)
                     }
                     true
                 }


                 menu.findItem(R.id.action_edit_favorite).setOnMenuItemClickListener {
                     rssItem?.let {
                         val i = Intent(context, EditFavoriteActivity::class.java)
                         i.putExtra(ARG.FEED_ITEM_ID, it.id)
                         context.startActivity(i)
                     }
                     true
                 }


                 menu.findItem(R.id.action_tag).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.onItemTagsEdit(it)
                     }
                     true
                 }
                 menu.findItem(R.id.action_read_all).setOnMenuItemClickListener {
                      actionCallback.makeAllRead()
                     true
                 }

                 menu.findItem(R.id.action_open_in_webview).setOnMenuItemClickListener {
                     openItemInWebView(context)
                     true
                 }

                 menu.findItem(R.id.action_copy).setOnMenuItemClickListener {
                     //copyToClipboard(context,titleTextView.text.toString())
                     clipboardString =titleTextView.text.toString()
                     true
                 }

                 menu.findItem(R.id.action_copy_link).setOnMenuItemClickListener {
                     rssItem?.link?.let{
                         //copyToClipboard(context,it)
                        clipboardString =it
                     }

                     true
                 }

                 menu.findItem(R.id.action_copy_inline_link).setOnMenuItemClickListener {
                     //copyToClipboard(context,linkStr!!)
                     clipboardString =linkStr
                     true
                 }

                 menu.findItem(R.id.action_copy_enclosure_link).setOnMenuItemClickListener {
                     rssItem?.enclosureLink?.let {
                         //copyToClipboard(context, it)
                        clipboardString =it
                     }
                     true
                 }

                 menu.findItem(R.id.action_attention_love_0).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markItemAttentionLevel(it,0)
                     }
                     true
                 }

                 menu.findItem(R.id.action_attention_love_1).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markItemAttentionLevel(it,1)
                     }
                     true
                 }

                 menu.findItem(R.id.action_attention_love_2).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markItemAttentionLevel(it,2)
                     }
                     true
                 }

                 menu.findItem(R.id.action_attention_love_3).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markItemAttentionLevel(it,3)
                     }
                     true
                 }

                 menu.findItem(R.id.action_attention_love_4).setOnMenuItemClickListener {
                     rssItem?.let{
                         actionCallback.markItemAttentionLevel(it,4)
                     }
                     true
                 }


                 rssItem?.feedId?.let{
                     menu.findItem(R.id.action_mark_as_read_late).isVisible = it != READ_LATE_FEED_ID
                     menu.findItem(R.id.action_mark_as_favorite).isVisible = it != FAVORITE_FEED_ID
                     menu.findItem(R.id.action_mark_as_memo).isVisible = it != MEMO_FEED_ID
                     menu.findItem(R.id.use_feed_rule).isVisible = it > 0
                     //menu.findItem(R.id.action_add_feed_rule).isVisible = it > 0
                     menu.findItem(R.id.action_mark_as_store).isVisible = it != STORE_FEED_ID
                     menu.findItem(R.id.action_delete).isVisible = it in SYSTEM_FEED_LIST
                     menu.findItem(R.id.action_edit_favorite).isVisible = it ==STORE_FEED_ID || it == FAVORITE_FEED_ID || it == MEMO_FEED_ID
                 }

                 rssItem?.let{item->
                     menu.findItem(R.id.action_attention_love_0).isEnabled = item.attentionLevel != 0
                     menu.findItem(R.id.action_attention_love_1).isEnabled = item.attentionLevel != 1
                     menu.findItem(R.id.action_attention_love_2).isEnabled = item.attentionLevel != 2
                     menu.findItem(R.id.action_attention_love_3).isEnabled = item.attentionLevel != 3
                     menu.findItem(R.id.action_attention_love_4).isEnabled = item.attentionLevel != 4

                     // Show/Hide enclosure
                     menu.findItem(R.id.feed_enclosure).isVisible = item.enclosureLink != null

                     menu.findItem(R.id.action_ad_feed_rule_image).isVisible = item.image_count == 1

                     menu.findItem(R.id.action_copy_link).isVisible = !item.link.isNullOrEmpty()
                     menu.findItem(R.id.action_copy_inline_link).isVisible = !linkStr.isNullOrEmpty()

                     // Add filename to tooltip
                     item.enclosureFilename?.let {
                         menu.findItem(R.id.action_open_enclosure).title = it

                         menu.findItem(R.id.action_open_enclosure).setOnMenuItemClickListener {
                             actionCallback.onEnclosureLinkClick(item)
                             true
                         }
                         menu.findItem(R.id.action_generate_enclosure_QR_code).setOnMenuItemClickListener {
                             actionCallback.generateEnclosureQRCode(item)
                             true
                         }

                         actionCallback.preLoadState(item).let {state->
                             menu.findItem(R.id.action_pre_download_enclosure).isVisible =
                                 PreLoadStateHelper.isStartAble(state)
                             menu.findItem(R.id.action_pause_pre_download_enclosure).isVisible=
                                 PreLoadStateHelper.isPauseAble(state)
                             menu.findItem(R.id.action_resume_pre_download_enclosure).isVisible=
                                 PreLoadStateHelper.isResumeAble(state)
                             menu.findItem(R.id.action_cancel_pre_download_enclosure).isVisible =
                                 PreLoadStateHelper.isCancelAble(state)
                             menu.findItem(R.id.action_del_pre_download_enclosure).isVisible =
                                 PreLoadStateHelper.isDelAble(state)
                         }

                         menu.findItem(R.id.action_pre_download_enclosure).setOnMenuItemClickListener {
                             actionCallback.downLoadEnclosure(item)
                             true
                         }

                         menu.findItem(R.id.action_pause_pre_download_enclosure).setOnMenuItemClickListener {
                             actionCallback.pauseDownLoadEnclosure(item)
                             true
                         }

                         menu.findItem(R.id.action_resume_pre_download_enclosure).setOnMenuItemClickListener {
                             actionCallback.resumeDownLoadEnclosure(item)
                             true
                         }

                         menu.findItem(R.id.action_cancel_pre_download_enclosure).setOnMenuItemClickListener {
                             actionCallback.cancelDownLoadEnclosure(item)
                             true
                         }

                         menu.findItem(R.id.action_del_pre_download_enclosure).setOnMenuItemClickListener {
                             actionCallback.delDownLoadEnclosure(item)
                             true
                         }

                     }

                     menu.findItem(R.id.action_show_current_feature).isVisible = item.feature!=null
                     menu.findItem(R.id.action_remove_feature).isVisible = (rssItem?.feature != null)
                     menu.findItem(R.id.action_mark_feature).setTitle(context.getString(when(item.feature!=null){true->  R.string.edit_feature  false->R.string.mark_feature}))
                 }
             }
         }
    }


    /**
     * Called when item has been measured, it is now the time to insert the image.
     *
     * @return Return true to proceed with the current drawing pass, or false to cancel.
     */
    override fun onPreDraw(): Boolean {
        loadImage()
        // Remove as listener
        itemView.viewTreeObserver.removeOnPreDrawListener(this)
        return true
    }

    protected open fun loadImage(){

    }

    fun loadFeedThumb(context: Context){
        rssItem?.feedThumb?.let{
            feedThumbImageView.visibility=View.VISIBLE
            GlideImageLoader.glide(context, it, true).into(feedThumbImageView)
        }
    }

    open fun clearHolder() {
       /*imageView.drawable?.let {
           if(it is BitmapDrawable){
               Timber.d("clear imageView drawable when feeditemholder removed.")
               it.bitmap?.recycle()
           }
       }*/
   }

    @SuppressLint("CheckResult")
    protected  fun loadImage(context: Context, imageView: ImageView, imageUrl:String, isEnclosure:Boolean){
        /*if(PrefUtils.shouldLoadImagesUseCoil(context)){
                           rssItem.imageUrl?.let{ CoilImageLoader.loadImageToImageView(context,it,imageView)}
                        }else {*/
        GlideImageLoader.glide(context, imageUrl,
                PrefUtils.shouldLoadImages(context))
                .centerCrop()
                .also {
                    it.error(
                            when (PrefUtils.isNightMode(context)) {
                                true -> when(isEnclosure){
                                    true-> R.drawable.ic_placeholder_music_white_48dp
                                    false-> R.drawable.placeholder_image_list_night_64dp
                                }
                                false -> when(isEnclosure){
                                    true-> R.drawable.ic_placeholder_music_night_48dp
                                    false-> R.drawable.placeholder_image_list_day_64dp
                                }
                            }
                    )
                }
                .into(imageView)
        //}
    }
}
